﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Ignitron.EEngine.Model;
using OpenTK;
using OpenTK.Graphics.OpenGL;

namespace Ignitron.EEngine.Adapters.OpenGL
{
    /// <summary>
    /// OpenTK Mesh representation, subclassed the general EMesh
    /// </summary>
    internal class OpenTKMesh: EMesh
    {
        /// <summary>
        /// Mesh data
        /// </summary>
        private Vector3[] mGLVertices;
        private Vector3[] mGLNormals;
        private Vector2[] mGLTexCoords;

        /// <summary>
        /// Updates the platform-specific data of the mesh
        /// </summary>
        protected override void Update()
        {
            // do the model conversion
            mGLVertices = mVertices.Select(v => new Vector3(v.X, v.Y, v.Z)).ToArray();
            mGLNormals = mNormals.Select(n => new Vector3(n.X, n.Y, n.Z)).ToArray();
            mGLTexCoords = mTexCoords.Select(tc => new Vector2(tc.X, tc.Y)).ToArray();
        }

        /// <summary>
        /// Rendering method
        /// </summary>
        internal void Render()
        {
            GL.PolygonMode(MaterialFace.Front, PolygonMode.Fill);
            GL.PolygonMode(MaterialFace.Back, PolygonMode.Fill);
            GL.CullFace(CullFaceMode.Back);

            // set buffers
            GL.VertexPointer<Vector3>(3, VertexPointerType.Float, 0, mGLVertices);
            GL.NormalPointer<Vector3>(NormalPointerType.Float, 0, mGLNormals);
            GL.TexCoordPointer<Vector2>(2, TexCoordPointerType.Float, 0, mGLTexCoords);

            // render
            GL.DrawElements<uint>(PrimitiveType.Triangles, mIndices.Length, DrawElementsType.UnsignedInt, mIndices);
        }

        /// <summary>
        /// Method for rendering normal vectors
        /// </summary>
        internal void RenderNormals(Vector4 color, float magnitude)
        {
            GL.Begin(PrimitiveType.Lines);
            GL.Color4(color);

            for (int i = 0; i < mGLVertices.Length; i++)
            {
                Vector3 v0 = mGLVertices[i];
                Vector3 n = mGLNormals[i];
                n.Normalize();
                n *= magnitude;
                Vector3 v1 = v0 + n;

                GL.Vertex3(v0);
                GL.Vertex3(v1);
            }

            GL.End();
        }

    }
}
